@@ -3,6 +3,9 @@ require 'assignable_types' |
||
3 | 3 |
require 'markdown_class_attributes' |
4 | 4 |
require 'utils' |
5 | 5 |
|
6 |
+# Agent is the core class in Huginn, representing a configurable, schedulable, reactive system with memory that can |
|
7 |
+# be sub-classed for many different purposes. Agents can emit Events, as well as receive them and react in many different ways. |
|
8 |
+# The basic Agent API is detailed on the Huginn wiki: https://github.com/cantino/huginn/wiki/Creating-a-new-agent |
|
6 | 9 |
class Agent < ActiveRecord::Base |
7 | 10 |
include AssignableTypes |
8 | 11 |
include MarkdownClassAttributes |
@@ -226,6 +229,9 @@ class Agent < ActiveRecord::Base |
||
226 | 229 |
!!@cannot_receive_events |
227 | 230 |
end |
228 | 231 |
|
232 |
+ # Find all Agents that have received Events since the last execution of this method. Update those Agents with |
|
233 |
+ # their new `last_checked_event_id` and queue each of the Agents to be called with #receive using `async_receive`. |
|
234 |
+ # This is called by bin/schedule.rb periodically. |
|
229 | 235 |
def receive! |
230 | 236 |
Agent.transaction do |
231 | 237 |
sql = Agent. |
@@ -256,9 +262,9 @@ class Agent < ActiveRecord::Base |
||
256 | 262 |
end |
257 | 263 |
|
258 | 264 |
# Given an Agent id and an array of Event ids, load the Agent, call #receive on it with the Event objects, and then |
259 |
- # save it with an updated _last_receive_at_ timestamp. |
|
265 |
+ # save it with an updated `last_receive_at` timestamp. |
|
260 | 266 |
# |
261 |
- # This method is tagged with _handle_asynchronously_ and will be delayed and run with delayed_job. It accepts Agent |
|
267 |
+ # This method is tagged with `handle_asynchronously` and will be delayed and run with delayed_job. It accepts Agent |
|
262 | 268 |
# and Event ids instead of a literal ActiveRecord models because it is preferable to serialize delayed_jobs with ids. |
263 | 269 |
def async_receive(agent_id, event_ids) |
264 | 270 |
agent = Agent.find(agent_id) |
@@ -273,6 +279,8 @@ class Agent < ActiveRecord::Base |
||
273 | 279 |
end |
274 | 280 |
handle_asynchronously :async_receive |
275 | 281 |
|
282 |
+ # Given a schedule name, run `check` via `bulk_check` on all Agents with that schedule. |
|
283 |
+ # This is called by bin/schedule.rb for each schedule in `SCHEDULES`. |
|
276 | 284 |
def run_schedule(schedule) |
277 | 285 |
types = where(:schedule => schedule).group(:type).pluck(:type) |
278 | 286 |
types.each do |type| |
@@ -280,7 +288,8 @@ class Agent < ActiveRecord::Base |
||
280 | 288 |
end |
281 | 289 |
end |
282 | 290 |
|
283 |
- # You can override this to define a custom bulk_check for your type of Agent. |
|
291 |
+ # Schedule `async_check`s for every Agent on the given schedule. This is normally called by `run_schedule` once |
|
292 |
+ # per type of agent, so you can override this to define custom bulk check behavior for your custom Agent type. |
|
284 | 293 |
def bulk_check(schedule) |
285 | 294 |
raise "Call #bulk_check on the appropriate subclass of Agent" if self == Agent |
286 | 295 |
where(:schedule => schedule).pluck("agents.id").each do |agent_id| |
@@ -288,10 +297,11 @@ class Agent < ActiveRecord::Base |
||
288 | 297 |
end |
289 | 298 |
end |
290 | 299 |
|
291 |
- # Given an Agent id, load the Agent, call #check on it, and then save it with an updated _last_check_at_ timestamp. |
|
300 |
+ # Given an Agent id, load the Agent, call #check on it, and then save it with an updated `last_check_at` timestamp. |
|
292 | 301 |
# |
293 |
- # This method is tagged with _handle_asynchronously_ and will be delayed and run with delayed_job. It accepts an Agent |
|
294 |
- # id instead of a literal Agent because it is preferable to serialize delayed_jobs with ids. |
|
302 |
+ # This method is tagged with `handle_asynchronously` and will be delayed and run with delayed_job. It accepts an Agent |
|
303 |
+ # id instead of a literal Agent because it is preferable to serialize delayed_jobs with ids, instead of with the full |
|
304 |
+ # Agents. |
|
295 | 305 |
def async_check(agent_id) |
296 | 306 |
agent = Agent.find(agent_id) |
297 | 307 |
begin |
@@ -1,3 +1,6 @@ |
||
1 |
+# AgentLogs are temporary records of Agent activity, intended for debugging and error tracking. They can be viewed |
|
2 |
+# in Agents' detail pages. AgentLogs with a `level` of 4 or greater are considered "errors" and automatically update |
|
3 |
+# Agents' `last_error_log_at` column. These are often used to determine if an Agent is `working?`. |
|
1 | 4 |
class AgentLog < ActiveRecord::Base |
2 | 5 |
attr_accessible :agent, :inbound_event, :level, :message, :outbound_event |
3 | 6 |
|
@@ -1,3 +1,5 @@ |
||
1 |
+# Contacts are used only for the contact form on the Huginn website. If you host a public Huginn instance, you can use |
|
2 |
+# these to receive messages from visitors. |
|
1 | 3 |
class Contact < ActiveRecord::Base |
2 | 4 |
attr_accessible :email, :message, :name |
3 | 5 |
|
@@ -1,5 +1,8 @@ |
||
1 | 1 |
require 'json_serialized_field' |
2 | 2 |
|
3 |
+# Events are how Huginn Agents communicate and log information about the world. Events can be emitted and received by |
|
4 |
+# Agents. They contain a serialized `payload` of arbitrary JSON data, as well as optional `lat`, `lng`, and `expires_at` |
|
5 |
+# fields. |
|
3 | 6 |
class Event < ActiveRecord::Base |
4 | 7 |
include JSONSerializedField |
5 | 8 |
|
@@ -16,10 +19,13 @@ class Event < ActiveRecord::Base |
||
16 | 19 |
where("events.created_at > ?", timespan) |
17 | 20 |
} |
18 | 21 |
|
22 |
+ # Emit this event again, as a new Event. |
|
19 | 23 |
def reemit! |
20 | 24 |
agent.create_event :payload => payload, :lat => lat, :lng => lng |
21 | 25 |
end |
22 | 26 |
|
27 |
+ # Look for Events whose `expires_at` is present and in the past. Remove those events and then update affected Agents' |
|
28 |
+ # `events_counts` cache columns. This method is called by bin/schedule.rb periodically. |
|
23 | 29 |
def self.cleanup_expired! |
24 | 30 |
affected_agents = Event.where("expires_at IS NOT NULL AND expires_at < ?", Time.now).group("agent_id").pluck(:agent_id) |
25 | 31 |
Event.where("expires_at IS NOT NULL AND expires_at < ?", Time.now).delete_all |
@@ -1,3 +1,4 @@ |
||
1 |
+# A Link connects Agents in a directed Event flow from the `source` to the `receiver`. |
|
1 | 2 |
class Link < ActiveRecord::Base |
2 | 3 |
attr_accessible :source_id, :receiver_id |
3 | 4 |
|
@@ -1,3 +1,4 @@ |
||
1 |
+# Huginn is designed to be a multi-User system. Users have many Agents (and Events created by those Agents). |
|
1 | 2 |
class User < ActiveRecord::Base |
2 | 3 |
# Include default devise modules. Others available are: |
3 | 4 |
# :token_authenticatable, :confirmable, |
@@ -1,5 +1,8 @@ |
||
1 | 1 |
#!/usr/bin/env ruby |
2 | 2 |
|
3 |
+# If you're using the backup gem, described on the Huginn wiki and at doc/deployment/backup, then you can use this |
|
4 |
+# utility to decrypt backups. |
|
5 |
+ |
|
3 | 6 |
in_file = ARGV.shift |
4 | 7 |
out_file = ARGV.shift || "decrypted_backup.tar" |
5 | 8 |
|
@@ -1,5 +1,8 @@ |
||
1 | 1 |
#!/usr/bin/env ruby |
2 | 2 |
|
3 |
+# This process is used to maintain Huginn's upkeep behavior, automatically running scheduled Agents and |
|
4 |
+# periodically propagating and expiring Events. It's typically run via foreman and the included Procfile. |
|
5 |
+ |
|
3 | 6 |
unless defined?(Rails) |
4 | 7 |
puts |
5 | 8 |
puts "Please run me with rails runner, for example:" |
@@ -1,5 +1,9 @@ |
||
1 | 1 |
#!/usr/bin/env ruby |
2 | 2 |
|
3 |
+# This process is used by TwitterStreamAgents to watch the Twitter stream in real time. It periodically checks for |
|
4 |
+# new or changed TwitterStreamAgents and starts to follow the stream for them. It is typically run by foreman via |
|
5 |
+# the included Procfile. |
|
6 |
+ |
|
3 | 7 |
unless defined?(Rails) |
4 | 8 |
puts |
5 | 9 |
puts "Please run me with rails runner, for example:" |